//
//  NSString+Utils.m
//  CJBusiness
//
//  Created by cuijin on 2017/12/22.
//

#import "NSString+Utils.h"

@implementation NSString (Utils)

/**
 *  @brief 判断当前字符串中是否包含子串
 *
 *  @param string 需要检查的子串
 *
 *  @return 如果当前字符串中包含子串，返回true，否则false
 */
- (BOOL)containsString:(NSString *)string {
    if (string.length == 0) {
        return NO;
    }
    
    return !NSEqualRanges([self rangeOfString:string], NSMakeRange(NSNotFound, 0));
}

- (BOOL)containsStringIgnoreCase:(NSString *)string {
    return [[self uppercaseString] containsString:[string uppercaseString]];
}

- (BOOL)match:(NSString *)regexp {
    if (regexp.length == 0) {
        return NO;
    }
    
    NSPredicate *regExPredicate = [NSPredicate predicateWithFormat:@"SELF matches %@", regexp];
    BOOL isMatch = [regExPredicate evaluateWithObject:self];
    return isMatch;
}


/**
 *  生成UUID
 *
 *  @return 生成的UUID字符串
 */
+ (NSString *)UUIDString {
    CFUUIDRef uuid = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, uuid);
    CFRelease(uuid);
    return (__bridge_transfer NSString *)string;
}


- (NSString *)trimBlank {
    return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}


- (BOOL)isNumber {
    int dotCount = 0;
    BOOL isLeagalNum = YES;
    
    for (NSUInteger i = 0; i < self.length; i++) {
        unichar cha = [self characterAtIndex:i];
        if (cha == '.') {
            dotCount++;
            if (dotCount >= 2) {
                isLeagalNum = NO;
                break;
            }
        }
        else if (cha >= '0' && cha <= '9') {
            ;
        }
        else {
            isLeagalNum = NO;
            break;
        }
        
    }
    
    return isLeagalNum;
}

/**
 *  包装SDK的subStringFromIndex:
 *
 *  @param from
 *
 *  @return 返回sub的字符串
 */
- (NSString *)subStringFromIndex:(NSUInteger)from
{
    if (from <= self.length) {
        return [self substringFromIndex:from];
    }
    else
    {
        NSAssert(YES, @"Error:length:%lu from:%lu", (unsigned long)self.length, (unsigned long)from);
        return nil;
    }
}

/**
 *  包装SDK的substringToIndex:
 *
 *  @param to
 *
 *  @return 返回sub的字符串
 */
- (NSString *)subStringToIndex:(NSUInteger)to
{
    if (to <= self.length) {
        return [self substringToIndex:to];
    }
    else
    {
        NSAssert(YES, @"Error:length:%lu to:%ld", (unsigned long)self.length, (unsigned long)to);
        return nil;
    }
}
/**
 *  包装SDK的subStringWithRange:
 *
 *  @param range
 *
 *  @return 返回sub的字符串
 */
- (NSString *)subStringWithRange:(NSRange)range
{
    if (range.location+range.length <= self.length) {
        return [self substringWithRange:range];
    }
    else
    {
        NSAssert(YES, @"Error:length:%lu Range(%ld,%ld)", (unsigned long)self.length, (unsigned long)range.location, (unsigned long)range.length);
        return nil;
    }
}

- (BOOL)equalIgnoreCase:(NSString *)cmpString {
    return [[self lowercaseString] isEqualToString:[cmpString lowercaseString]];
}

- (NSString *)trimmedString
{
    return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

-(BOOL)isEmpty{
    return self == nil || self.length == 0 || [self trimmedString].length == 0;
}

/**
 * jsonString 转换 NSDictionary
 */
-(NSDictionary *)dictionaryValue{
    NSError *errorJson;
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[self dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&errorJson];
    if (errorJson != nil) {
#ifdef DEBUG
        NSLog(@"fail to get dictioanry from JSON: %@, error: %@", self, errorJson);
#endif
    }
    return jsonDict;
}

-(NSString*)escapeBySql {
    if (self.length == 0) {
        return @"";
    }
    NSString *str = nil;
    // ' --> ''
    str = [self stringByReplacingOccurrencesOfString:@"'" withString:@"''"];
    
    // " --> ""
    str = [str stringByReplacingOccurrencesOfString:@"\"" withString:@"\"\""];
    
    // \ -->  (remove backslashes)
    str = [str stringByReplacingOccurrencesOfString:@"\\\\" withString:@""];
    
    return str;
}

@end


#pragma mark - String URL相关

@implementation NSString(URL)

/**
 *  URL参数转义，空格会换成+
 *
 *  @return 转义之后的URL字符串
 */
- (NSString *)escapingForURLQuery {
    NSString *result = self;
    
    static CFStringRef leaveAlone = CFSTR(" ");
    static CFStringRef toEscape = CFSTR("\n\r:/=,!$&'()*+;[]@#?%");
    
    CFStringRef escapedStr = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)self, leaveAlone,
                                                                     toEscape, kCFStringEncodingUTF8);
    
    if (escapedStr) {
        NSMutableString *mutable = [NSMutableString stringWithString:(__bridge NSString *)escapedStr];
        CFRelease(escapedStr);
        
        [mutable replaceOccurrencesOfString:@" " withString:@"+" options:0 range:NSMakeRange(0, [mutable length])];
        result = mutable;
    }
    return result;
}

/**
 *  转义之后的URL参数还原，+会被还原成空格
 *
 *  @return 还原之后URL参数
 */
- (NSString *)unEscapingFromURLQuery {
    NSString *deplussed = [self stringByReplacingOccurrencesOfString:@"+" withString:@" "];
    return [deplussed stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}

/**
 *  字符串转换成URL对象，#会在内部处理
 *
 *  @return 转换成的URL对象
 */
- (NSURL *)toURL {
    if (self.length == 0) {
        return NULL;
    }
    
    NSString *tmpUrl = self;
    
    tmpUrl = [tmpUrl stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSRange sRange = [tmpUrl rangeOfString:@"#"] ;
    
    NSString *retUrlStr = tmpUrl;
    
    if (sRange.location != NSNotFound) {
        NSString *prefix = [[tmpUrl substringToIndex:sRange.location] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSURL *url  = [NSURL URLWithString:prefix];
        
        NSString *sufix = [[tmpUrl substringFromIndex:sRange.location+1] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        retUrlStr= [[url absoluteString] stringByAppendingFormat:@"#%@",sufix];
    }
    else {
        retUrlStr = [retUrlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    }
    
    return [NSURL URLWithString:retUrlStr];
    
}

/**
 *  对URL做UTF8编码
 *
 *  @return UTF8编码之后的URL字符串
 */
- (NSString *)URLEncode {
    return [self stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}

/**
 *  对URL做UTF8解码
 *
 *  @return UTF8解码之后的URL字符串
 */
- (NSString *)URLDecode {
    return [self stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}


/**
 *  对NSString做URLEncode编码
 *
 *  @return NSString的URLEncode字符串
 */
- (NSString *)stringURLEncoded {
    NSString *result=(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                           (CFStringRef)self,
                                                                                           NULL,
                                                                                           CFSTR("!*'();:@&=+$,/?%#[]"),
                                                                                           kCFStringEncodingUTF8));
    return result;
}
/**
 *  对NSString做URLDecoded编码
 *
 *  @return NSString的URLDecoded字符串
 */
-(NSString *)stringURLDecode {
    NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
                                                                                                             (CFStringRef)self,
                                                                                                             CFSTR(""),
                                                                                                             kCFStringEncodingUTF8));
    return result;
    
}

/**
 *  对NSString做URIEncoded编码
 *
 *  @return NSString的URIEncoded字符串
 */
-(NSString*)encodeAsURIComponent {
    const char *p=[self UTF8String];
    NSMutableString *result=[NSMutableString string];
    for (; *p!=0; p++) {
        unsigned char c=*p;
        if (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '-' || c == '_')
        {
            [result appendFormat:@"%c",c];
        }else {
            [result appendFormat:@"%%%02X",c];
        }
        
    }
    return result;
}

@end

#pragma mark - String Hash相关

@implementation NSString(Hash)

/**
 * @brief 计算NSString的MD5哈希函数
 *
 * @return 返回NSString的MD5哈希值，长度32，大写
 */
- (NSString *)MD5 {
    const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:strlen(cstr)];
    return [data MD5];
}
/**
 * @brief 计算NSString的SHA1哈希函数
 *
 * @return 返回NSString的SHA1哈希值，长度40，大写
 */
- (NSString *)SHA1 {
    const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:strlen(cstr)];
    return [data SHA1];
}

/**
 * @brief 计算NSString的SHA256哈希函数
 *
 * @return 返回NSString的SHA256哈希值，长度64，大写
 */
- (NSString *)SHA256 {
    const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:strlen(cstr)];
    return [data SHA256];
}


@end
